package com.suduku.entity;

import lombok.Data;

import java.util.List;
import java.util.Objects;

/**
 * 链 <br/>
 * 由两个单元格组成，分强链和弱链
 * 强链：当前区域内，候选值 有且只有 两个空白格，强链也可以是弱链
 * 弱链：当前区域内，候选值 至少有 两个空白格
 * 链必须由强链开始，强链结束
 * B1--B2..B3--B4..B5--B6（"--"：强链，".."：弱链）
 *
 * 当前的end与next.head，形成弱链
 *
 * @author chena
 */
@Data
public class Chain {

    /** 链头 */
    private Box head;
    /** 链尾 */
    private Box end;
    /** 链类型：true-强；false-弱 */
    private boolean type;
    /** 上一条链 */
    private Chain pre;
    /** 下一条链 */
    private Chain next;

    /**
     * 功能描述: 构造强链 <br/>
     *
     * @param list 两个点
     */
    public Chain(List<Box> list) {
        if(list.size() != 2) {
            return;
        }
        this.head = list.get(0);
        this.end = list.get(1);
        this.type = true;
    }

    /**
     * 功能描述: 构造弱链 <br/>
     *
     * @param head 节点1
     * @param end 节点2
     * @return "null"
     */
    public Chain(Box head, Box end) {
        this.head = head;
        this.end = end;
        this.type = false;
    }

    public Chain(Box head, Box end, boolean type) {
        this.head = head;
        this.end = end;
        this.type = type;
    }

    /**
     * 功能描述: 交换头尾 <br/>
     */
    public void exchange() {
        Box tmp = this.head;
        this.head = this.end;
        this.end = tmp;
    }

    /**
     * 功能描述: 添加下一条链 <br/>
     *
     * @param chain 链
     * @return "boolean"
     */
    public boolean add(Chain chain) {
        // 两条强链之间，就是弱链
        if(this.equals(chain)) {
            return false;
        }
        if(!addNext(chain)) {
            chain.exchange();
            return addNext(chain);
        }
        return true;
    }

    /**
     * 功能描述: 校验下一个头节点与当前尾节点，是否再同行、列、宫。任何一个满足即可 <br/>
     *
     * @param chain 下一个链
     * @return "boolean"
     */
    private boolean addNext(Chain chain) {
        if(this.end.getX() == chain.getHead().getX()
                || this.end.getY() == chain.getHead().getY()
                || this.end.getG() == chain.getHead().getG()) {
            // 当前下一条指向chain
            setNext(chain);
            // 下一条的上一条指向当前
            chain.setPre(this);
            chain.setNext(null);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Chain)) return false;
        Chain chain = (Chain) o;
        // 四个值都不相等
        return Objects.equals(head, chain.head)
                || Objects.equals(end, chain.end)
                || Objects.equals(head, chain.end)
                || Objects.equals(end, chain.head)
                || Objects.equals(head, end)
                || Objects.equals(chain.head, chain.end);
    }

    @Override
    public int hashCode() {
        return Objects.hash(head, end);
    }


}
